iT邦幫忙

2026 iThome 鐵人賽

DAY 13
0
Claude AI

Claude × Playwright:30 天打造你的 Agentic SDET 同事系列 第 15

Day 15|不要再告訴它每一步:從 Test Case 到 Exploration Charter

  • 分享至 

  • xImage
  •  

前言

在前幾天,我們都是告訴新同事我們需要什麼,而新同事幫我們去做這些工作。但今天呢,我們希望我們的同事可以更獨立一點,所以我們將不會告訴他要做哪些事情了。

從今天開始,新同事自己決定目標、自己決定界線,並且要如何探索。我們的角色將會從原本決策者變成一個 Mentor,而新同事則是除了執行者也是決策者。

而今天要教會他的東西就是,撰寫一份 Exploration Charter。

為什麼不繼續寫 test case

Test case 有個很難承認的限制:它只驗得到你已經想到的那條路。 你寫「購買兩件商品,把數量改成零,檢查總金額不是負數」,它就永遠只會做這件事。負數這個點子是你想到的,那 charter 產生的價值就等於你的想像力,一個字都不會多。

這件事在人身上還算划算,因為人邊走邊想。但交給 agent 之後就不划算了:你多寫一步,它就多走一步,你沒寫的它一步都不會走。把每一步都寫死,等於花錢請它幫你按滑鼠。

要讓它走出你沒想過的路,你能給的就只剩三樣:要達成什麼、憑什麼算對、哪裡不准去。路怎麼走留給它。這三樣寫成一份檔案,就是 charter。

換句話說,這一天真正在做的事不是「換一種格式寫測試」,是把控制權從步驟移到判準。步驟你放手,判準你抓緊;抓不緊的時候它會走得很遠,但走去哪裡你管不著。

實驗:一句話進去,它補了六條你沒說的界線

exploration-charter 是使用者才能觸發的 skill,agent 不會因為某些關鍵詞自己叫它。所以下指令的時候,目標和範圍要自己講清楚:

/sdet-skills:exploration-charter 探索 https://with-bugs.practicesoftwaretesting.com 的結帳流程,找付款相關的 bug

輸入就這一句。它寫出 charters/toolshop-checkout-payment.yaml

# 探索章程(exploration charter)
# 由 exploration-charter 產生、供 explore 讀取的輸入。
# 位置慣例:charters/<slug>.yaml(committed;output/evidence/ 才是每次跑的輸出、被 gitignore)
charter:
  goal: "在 with-bugs build 走完 Toolshop 的結帳流程,找付款與金額計算相關的 bug"
  target: "https://with-bugs.practicesoftwaretesting.com/#/?bug-hunting=true"
  scope: [商品頁, 購物車, 結帳表單, 配送資訊, 付款方式, 訂單確認頁]

  oracles:
    - "金額內部一致:單價 × 數量 = 小計,小計 + 運費 − 折扣 = 應付總額,購物車與結帳頁與確認頁三處數字要一致"
    - "付款失敗時要有明確錯誤訊息,而且不得建立訂單;成功才有訂單編號"
    - "UI 顯示的結果要與 API 狀態碼一致"
    - "正常操作不應出現 console error"

  out_of_bounds:
    - "不得對正式站 practicesoftwaretesting.com 做任何操作,只打 with-bugs 這個 build"
    - "不得修改或刪除既有他人資料,只能動自己這輪建立的購物車與訂單"
    - "不得使用或嘗試取得 admin 權限"
    - "不得做安全類測試(SQLi、越權列舉)—— 這輪的目標是金額與付款邏輯"
    - "不得寫迴圈連打端點"
    - "不得對外部金流服務送出真實請求"

  test_account: customer@practicesoftwaretesting.com   # 帳密走 env:TOOLSHOP_TEST_USER / env:TOOLSHOP_TEST_PASS
  max_steps: 25

把輸入跟產出擺在一起比,差別在這裡:

欄位 你講了嗎
goaltarget 講了
scope 六個畫面 沒講,它從「結帳流程」展開
oracles 四條 沒講,它從「付款相關」推出判準
out_of_bounds 六條 一條都沒講
test_account 走環境變數 沒講
max_steps: 25 沒講

一句話進去,六條界線出來。這些不是它憑空想的。exploration-charter 這支 skill 自己規定了 out_of_bounds 的最低涵蓋範圍:不對 production 寫入、不付款、只用測試帳號;要走端點時再加一層,不打 config/product-context.md 標記「不得碰」的端點、不做資料列舉、不自動化連打。剩下那幾條是它讀了這個站的情況補的(正式站與 with-bugs 是兩個 build、這輪的目標是金額不是安全)。Day 5 寫的產品知識與 Day 6 立的權責,在這裡第一次派上用場。

左邊是你輸入的一句話,右邊是產出的 charter 逐欄位標示哪些是你講的、哪些是它補的

七個欄位裡,你只講了兩個。

這一步的意義是:護欄不該靠你每次記得寫。你會忘記「不要打正式站」,但一份會自動補上這條的 skill 不會忘。你的工作從「想齊所有該禁止的事」變成「檢查它補的這幾條夠不夠」,後者你做得到,前者你做不到。

Charter 不是 test case

Exploration Charter 中文寫成探索章程(Charter),但它更像一份任務書。傳統的測試案例會告訴你每一步怎麼做、每一步該看到什麼,只檢驗那一條路線。章程不一樣,它給目標、不給路徑;對錯交給 oracle 判,路線由執行的人自己決定。

Test Case Exploration Charter
寫的是 怎麼走(步驟) 要達成什麼(目標)
路徑 寫死 留白
判對錯 每一步的預期結果 oracle
安全靠什麼 步驟本身不會越界 out_of_bounds 護欄
能發現新東西嗎 只驗得到寫下的那條 走沒人想過的路

舉個例子,如果 test case 寫「購買兩件商品,並且把數量改成零,檢查總金額不是負數」,這就是一個測試案例。

但 charter 只會寫「探索購物車和結帳,最後的金額要算得正確」。要不要把數量改成零,由執行 charter 的人自己決定,或是自己想出來。

Charter 由四個東西組成:

  • goal:用一句話表示要達成的目標
  • scope:可以去瀏覽哪些頁面,甚至是哪些區域
  • oracles:怎麼算是預期的結果,或是正確的結果
  • out_of_bounds:在範圍之外,而且不能執行

甜蜜點:目標明確、路徑開放、界線清楚

在撰寫 charter 的時候,很容易把它寫得太細。例如在 scope 裡面描述了操作的步驟,那它就會造成這個步驟冗長,基本上來說它就變成像是一個 test case,但可能是更難維護的一份成本。

另一種是寫得太廣泛。例如目標寫了「測試購物車」,但沒有告訴它怎樣的行為是正確的(也就是沒有給 oracle),那它就會去瀏覽購物車的流程,但因為不知道什麼是正常的,可能會忽略掉某些 bug,認為系統是正常的。

兩種偏差都有實跑的數字可以看。

太窄的那一邊。 上面那張 toolshop-checkout-payment.yaml 圈了六個畫面、max_steps: 25、oracle 只管金額與 console。它第一次實跑(2026-08-08)交回 3 筆發現,全部命中既有指紋,新的是 0 筆。原因寫在那輪的 log 裡:金額類缺陷在一週前那輪已經掃過一遍,charter 把範圍圈在同一塊地。這不是它偷懶,是 charter 指定它去挖一個已經挖過的坑。

太廣的那一邊。 charters/academybugs.yaml 面對的是一個有標準答案的站:站方宣稱植入 25 支 bug。第一版 charter 的 oracle 寫得很像「常識清單」,例如「圖片與商品相符」「表單驗證要擋」。探索兩輪,獨立命中 17 支,0.68。

漏掉的 8 支不是能力問題,是判準問題。那一版 charter 的判準全是相對的:問它「這張圖跟其他張一不一樣」。18 張列表圖裡只有一張離群,抓到了;另外 14 張一致地沒填滿容器,因為彼此一致,所以一個訊號都沒有。

Charter 是活的:漏掉的東西要回填

那 8 支後來收斂成四條根因,逐條寫回 charters/academybugs.yaml,而不是另開一份檢討文件:

根因 原本錯在哪 改成什麼
每條相對判準配一條絕對判準 問「跟其他張一不一樣」,一致地錯就沒訊號 量 rendered height 是否等於容器 height
靜態解析只用來選目標 分享鈕 href 看起來正常,事件處理器攔截後才改開拼錯網域 每一顆都實際點過,看最終落地 URL 與狀態
通過條件寫到終態 「表單可載入、可送出」記成 OK,實際送出後 loader 永遠轉 等到成功訊息、錯誤訊息或逾時三者之一才記結果
把沒被畫面主動端出來的東西列進計畫 minicart 收合時 DOM 裡沒有商品標題,忘記密碼整條沒走 scope 列到 URL 層級,收合元件單獨列一條

同一次回填還動了兩個地方:scope 從功能區塊名稱展開成五條實際 URL(/account/?ec_page=forgot_password 那條前兩輪從沒走過,裡面藏著一支 bug),max_steps 從 40 改成 60,理由直接寫在該行後面:「40 不足以同時做完 18 商品的廣度與交叉配對的深度」

補完之後第三輪以站方的答案校準,25 支補齊。

這件事的重點不在 25 這個數字,在於修正留在 charter 檔裡,而且指得到是哪幾筆逼出來的(每條根因都掛著 caught: [F-021, F-031] 這種欄位)。下一輪讀 charter 的人不必知道這段歷史,也會拿到已經修好的判準。

小結

一句話發動 exploration-charter,它產出一份 YAML,你只講了目標,它補上 scope、oracle、六條界線、步數上限與憑證來源;你檢查它補的夠不夠,而不是從零想齊所有該禁止的事。跑完之後不要把 charter 當一次性的輸入丟掉:漏掉什麼、判準為什麼接不住、步數為什麼不夠,全部回填到同一份檔案,下一輪直接站在修好的版本上開始。

              一句話:目標 + 網址
                        │
                        ▼
            /sdet-skills:exploration-charter
              (讀專案授權分級與 knowledge/)
                        │
                        ▼
              charters/<slug>.yaml
        goal|scope|oracles|out_of_bounds
              + max_steps + 憑證來源
                        │
                        ▼
                  人審一次:夠不夠
              太窄?判準相對?步數不足?
                        │
                        ▼
                  交給 explore 跑一輪
                        │
                        ▼
              漏掉的收斂成根因,回填 charter
              (scope 展開、判準改絕對、步數調高)
                        │
                        └──────► 下一輪讀的是修好的版本

charter 給的是目標、判準與界線,不是步驟,步驟寫死等於花錢請它按滑鼠。護欄也不該靠你每次記得寫,那六條 out_of_bounds 你一條都沒講,而它每次都會補上。而 charter 是活的,academybugs 那份從 17/25 走到 25/25,靠的不是換一支更強的 agent,是把漏掉的四個根因寫回同一份檔案。

下一步

charter 寫好了,但它現在只是一份躺在 charters/ 裡的 YAML。

明天把它交出去:explore 拿著這份章程,自己決定第一步點哪裡、下一步往哪走。這裡會冒出一個新問題,它憑什麼認為這一步比那一步值得走? 還有一個更現實的,它怎麼記得自己已經走過哪裡,不要在同一個畫面上鬼打牆。


參考資料

  1. Elisabeth Hendrickson — Explore It! - charter 這個概念的來源:目標明確、路徑開放
  2. James Bach — Session-Based Test Management - charter 加上一段有時限的 session,探索才管得動
  3. James Bach — Exploratory Testing - Rapid Software Testing 對探索式測試的定義
  4. Toolshop(Practice Software Testing)with-bugs build - 本篇產出的那張 charter 的受測站
  5. AcademyBugs - 站方宣稱植入 25 支 bug,本篇校準那一段的外部標準答案
  6. 本專案 charters/toolshop-checkout-payment.yaml - 一句話產出的那份
  7. 本專案 charters/academybugs.yaml - 含 2026-08-01 回填的四條 coverage_rulesscope_urls
  8. 本專案 skills/explore/exploration-charter/ - 產生 charter 的 skill
  9. 本專案 docs/explore/explore.md - 覆蓋鐵則的來由

上一篇
Day 14|第一次寫 Bug Report:從發現到可重現報告
下一篇
Day 16|教它自己選下一步,而且不鬼打牆:Action Selection 與路徑記憶
系列文
Claude × Playwright:30 天打造你的 Agentic SDET 同事16
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言